
#include <ctime>
#include <iostream> 
#include <algorithm>
#include <thread>
#include <random>
#include <string>
#include <numbers>
#include <format>
#include <string_view>
#include <cstdio>

using namespace std;

template <typename... Args>
void print(const string_view fmt_str, Args&&... args) {
	auto fmt_args{ make_format_args(args...) };
	string outstr{ vformat(fmt_str, fmt_args) };
	fputs(outstr.c_str(), stdout);
}
// std::print need C++23

// 定义一个结构体表示分数
struct Frac {
	long n;
	long d;
};
// Frac类型的格式化特化 
template<>
struct std::formatter<Frac>
{
	/*parse() 函数解析格式字符串，从冒号之后 (若没有冒号，则在开大括号之后)
		直到但不包括结 束大括号 (就是指定对象类型的部分)。其接受一个 ParseContext
		对象，并返回一个迭代器。这 里，可以只返回 begin()
		迭代器。因为我们的类型不需要新语法，所以无需准备任何东西。
		*/
	template < typename ParseContext>
	constexpr auto parse(ParseContext& ctx) {
		return ctx.begin();
	}

	/*format() 函数接受一个 Frac 对象和一个 FormatContext 对象，返回结束迭代器。format_to() 函
		数可使这变得很容易，其可以接受一个迭代器、一个格式字符串和一个参数包。本例中，参
		数包是 Frac 类的两个属性，分子和分母。
		需要做的就是提供一个简单的格式字符串“{0}/{1}”以及分子和分母的值 (0 和 1 表示参数的
		位置)*/
	template < typename FormatContext>
	auto format(const Frac& f, FormatContext& ctx) {
		return format_to(ctx.out(), "{0:d}/{1:d}", f.n, f.d);
	}
};

void testFrac()
{
	Frac f{ 5, 3 };
	print("Frac: {}\n", f);
}


void test1() {

	string who{ "every one" };
	int ival{ 42 };
	double pi{ std::numbers::pi };

	cout << format("Hello,{}!\n", who);
	cout << format("Integer:{}!\n", ival);
	cout << format("π={}!\n", pi);
	cout << format("Hello {1} {0}\n", ival, who); // Hello everyone 42
	cout << format("Hello {0} {1}\n", ival, who); // Hola 42 everyone
	cout << format("{:.<10}\n", ival); // 42........
	cout << format("{:.>10}\n", ival); // ........42
	cout << format("{:.^10}\n", ival); // ....42....
	cout << format("π: {:.5}\n", pi); // π: 3.1416
}

void test2() {

	string who{ "every one" };
	int ival{ 42 };
	double pi{ std::numbers::pi };

	print("Hello,{}!\n", who);
	print("Integer:{}!\n", ival);
	print("π={}!\n", pi);
	print("Hello {1} {0}\n", ival, who); // Hello everyone 42
	print("Hello {0} {1}\n", ival, who); // Hola 42 everyone
	print("{:.<10}\n", ival); // 42........
	print("{:.>10}\n", ival); // ........42
	print("{:.^10}\n", ival); // ....42....
	print("π: {:.5}\n", pi); // π: 3.1416
}

int main(int argc, char const* argv[])
{
	testFrac();

	return 0;
}

